home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / QuickTime VR / MacOS / QuickDraw™ 3D 1.0.6F4 SDK / Samples / SampleCode / View3DMF NetScape Plugin / View3DMF Plugin / View3DMF.cp < prev    next >
Encoding:
Text File  |  1996-03-10  |  15.4 KB  |  603 lines  |  [TEXT/MMCC]

  1. //View3DMF.cp
  2. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3. //
  4. // Quickdraw 3D sample code
  5. //
  6. // Netscape plugin for displaying a stream of 3DMF data
  7. //
  8. // Rick Evans, AppleLink: DEVSUPPORT (devsupport@applelink.apple.com)
  9. //
  10. // The following functions were adapted from the NetScape sample ViewPict.
  11. //
  12. // ©1996 Apple Computer Inc., All Rights Reserved
  13. //
  14. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  15.  
  16. #ifndef _NPAPI_H_
  17. #include "npapi.h"
  18. #endif
  19.  
  20. // for QuickDraw 3D
  21. #include <QD3D.h>
  22. #include <QD3DMath.h>
  23. #include <QD3DGroup.h>
  24. #include <QD3DStyle.h>
  25. #include <QD3DView.h>
  26.  
  27. #include "View3DMF.h"
  28. #include "MetaFileView.h"
  29. #include "MyErrorHandler.h"
  30.  
  31. static OSErr    AppendData(PluginInstance* This, unsigned long* len, void *buffer) ;
  32. static Boolean    StartDraw(NPWindow* window);
  33. static void        EndDraw(NPWindow* window);
  34. static void        DoDraw(PluginInstance* This);
  35.  
  36. CGrafPort gSavePort;
  37. CGrafPtr gOldPort;
  38.  
  39.  
  40. //------------------------------------------------------------------------------------
  41. // NPP_Initialize:
  42. // Called the first time the plugin is loaded this Netscape Navigator session.
  43. //------------------------------------------------------------------------------------
  44. NPError
  45. NPP_Initialize(void)
  46. {
  47.     TQ3Status    myStatus;
  48.     
  49.     //    Initialize QuickDraw 3D, open a connection to the QuickDraw 3D library
  50.     myStatus = ::Q3Initialize();
  51.     if ( myStatus == kQ3Failure ) 
  52.     {
  53.         return(NPERR_MODULE_LOAD_FAILED_ERROR); // ??? Is there a better error?
  54.     }
  55.  
  56.     // install the error handler
  57.     // these gets called whenever a QD3D error occurs
  58.     ::Q3Error_Register( MyErrorHandler, 0L );        
  59.     ::Q3Warning_Register( MyWarningHandler, 0L );        
  60.  
  61.     // create region used by netscape to save GrafPort state.
  62.     gSavePort.clipRgn = ::NewRgn();
  63.     return NPERR_NO_ERROR;
  64. }
  65.  
  66.  
  67. //------------------------------------------------------------------------------------
  68. // NPP_Shutdown:
  69. // Called when plugin is unuloaded, usually when Netscape Navigator is shutdown.
  70. //------------------------------------------------------------------------------------
  71. void 
  72. NPP_Shutdown(void)
  73. {
  74.     TQ3Status    myStatus;
  75.  
  76.     //    Close our connection to the QuickDraw 3D library
  77.     myStatus = ::Q3Exit();
  78.  
  79.     if ( myStatus == kQ3Failure )
  80.         DebugStr("\pQ3Exit returned failure.");
  81.  
  82.     // release region used by netscape to save GrafPort state.
  83.     if (gSavePort.clipRgn)
  84.         ::DisposeRgn(gSavePort.clipRgn);
  85. }
  86.  
  87.  
  88. //------------------------------------------------------------------------------------
  89. // NPP_New:
  90. // Called to create a new instance of plugin.
  91. //------------------------------------------------------------------------------------
  92. NPError 
  93. NPP_New(NPMIMEType pluginType,    // MIME type that this plug-in is handling
  94.                 NPP instance,    // handle which uniquely describes this instance
  95.                 uint16 mode,    // indicates whether this instance is embedded or not
  96.                 int16 argc,
  97.                 char* argn[],
  98.                 char* argv[],
  99.                 NPSavedData* saved)
  100. {
  101.     if (instance == NULL)
  102.         return NPERR_INVALID_INSTANCE_ERROR;
  103.         
  104.     instance->pdata = NPN_MemAlloc(sizeof(PluginInstance));
  105.     PluginInstance* This = (PluginInstance*) instance->pdata;
  106.     if (This != NULL)
  107.     {
  108.         TQ3Point3D        myOrigin = { 0.0, 0.0, 0.0 } ;
  109.  
  110.         This->fWindow = NULL;
  111.  
  112.         This->fMode = mode;    // Mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h)
  113.  
  114.         This->fBuffer = NULL;
  115.         This->fBufferLength = 0;
  116.         
  117.         This->fView = NULL;
  118.         
  119.         SetRect (&This->fRect, 0, 0, 50, 50);
  120.  
  121.         // the main display group:
  122.         This->fModel = NULL ;
  123.  
  124.         // the drawing styles:
  125.         This->fInterpolation = ::Q3InterpolationStyle_New(kQ3InterpolationStyleNone) ;
  126.         if (This->fInterpolation == NULL)
  127.             goto bail;
  128.  
  129.         This->fBackFacing = ::Q3BackfacingStyle_New(kQ3BackfacingStyleRemove ) ;
  130.         if (This->fBackFacing == NULL)
  131.             goto bail1;
  132.  
  133.         This->fFillStyle = ::Q3FillStyle_New(kQ3FillStyleFilled ) ;
  134.         if (This->fFillStyle == NULL)
  135.             goto bail2;
  136.  
  137.         This->fGroupScale = 1;                
  138.         This->fGroupCenter = myOrigin ;            
  139.  
  140.         // set the rotation matrix the identity matrix
  141.         ::Q3Matrix4x4_SetIdentity(&This->fRotation);    
  142.  
  143.         return NPERR_NO_ERROR;
  144.     }
  145.     else
  146.     {
  147.          SysBeep (1L);
  148.         goto bail;
  149.     }
  150.  
  151. bail2:
  152.         ::Q3Object_Dispose(This->fBackFacing);
  153. bail1:
  154.         ::Q3Object_Dispose(This->fInterpolation);
  155. bail:
  156.         SysBeep (1L);
  157.         return NPERR_OUT_OF_MEMORY_ERROR;
  158. }
  159.  
  160.  
  161.  
  162.  
  163. //------------------------------------------------------------------------------------
  164. // NPP_Destroy:
  165. // Called to delete a specific instance of a plug-in
  166. //------------------------------------------------------------------------------------
  167. NPError 
  168. NPP_Destroy(NPP instance, NPSavedData** save)
  169. {
  170.     if (instance == NULL)
  171.     {
  172.         return NPERR_INVALID_INSTANCE_ERROR;
  173.     }
  174.  
  175.     PluginInstance* This = (PluginInstance*) instance->pdata;
  176.  
  177.     if (This != NULL)
  178.     {
  179.         if (This->fView != NULL)
  180.         {
  181.             ::Q3Object_Dispose(This->fView) ;                // the view for the scene
  182.         }
  183.  
  184.         if (This->fModel != NULL)
  185.         {
  186.             ::Q3Object_Dispose(This->fModel) ;            // object in the scene being modelled
  187.             This->fModel = NULL ;
  188.         }
  189.         
  190.         if (This->fInterpolation != NULL)
  191.         {
  192.             ::Q3Object_Dispose(This->fInterpolation) ;    // interpolation style used when rendering
  193.         }
  194.     
  195.         if (This->fBackFacing != NULL)
  196.         {
  197.             ::Q3Object_Dispose(This->fBackFacing) ;        // whether to draw shapes that face away from the camera
  198.         }
  199.     
  200.         if (This->fFillStyle != NULL)
  201.         {
  202.             ::Q3Object_Dispose(This->fFillStyle) ;        // whether drawn as solid filled object or decomposed to components
  203.         }
  204.     
  205.         if (This->fBuffer)
  206.         {
  207.             ::DisposeHandle(This->fBuffer);
  208.             This->fBuffer = NULL;
  209.             This->fBufferLength = 0;
  210.         }
  211.  
  212.         NPN_MemFree(instance->pdata);
  213.  
  214.         instance->pdata = NULL;
  215.     }
  216.  
  217.     return NPERR_NO_ERROR;
  218. }
  219.  
  220.  
  221.  
  222. //------------------------------------------------------------------------------------
  223. // NPP_SetWindow:
  224. // Called to provide a window for the plug-in to draw into.
  225. //------------------------------------------------------------------------------------
  226. NPError 
  227. NPP_SetWindow(NPP instance, NPWindow* window)
  228. {    
  229.     NP_Port         *port         = (NP_Port *) window->window ;
  230.     TQ3CameraObject    holdCamera    = NULL;
  231.  
  232.     if (instance == NULL)
  233.     {
  234.         return NPERR_INVALID_INSTANCE_ERROR;
  235.     }
  236.  
  237.     PluginInstance* This = (PluginInstance*) instance->pdata ;
  238.  
  239.     if (This->fView != NULL)
  240.     {
  241.         ::Q3View_GetCamera(This->fView, &holdCamera);    // keep reference to camera 
  242.         ::Q3Object_Dispose(This->fView) ;
  243.     }
  244.  
  245.     SetRect (&This->fRect, 0, 0, window->width, window->height ) ;
  246.  
  247.     This->fView = MyNewView( (GrafPtr) port->port, &This->fRect ) ;
  248.  
  249.     if (This->fView == nil)
  250.     {
  251.         return NPERR_GENERIC_ERROR; /// ??? Got a better error?
  252.     }
  253.  
  254.     if (holdCamera != NULL)
  255.     {
  256.         ::Q3View_SetCamera(This->fView, holdCamera);    // restore saved camera onject
  257.         ::Q3Object_Dispose(holdCamera) ;                // decrement reference count
  258.     }
  259.  
  260.     This->fWindow = window;
  261.  
  262.     return NPERR_NO_ERROR;
  263. }
  264.  
  265.  
  266.  
  267. //------------------------------------------------------------------------------------
  268. // NPP_NewStream:
  269. // Called to notifies an instance of a new data stream.
  270. //------------------------------------------------------------------------------------
  271. NPError NPP_NewStream(NPP instance,
  272.                             NPMIMEType type, //MIME-type of the stream 
  273.                             NPStream *stream,    
  274.                             NPBool seekable, // is stream known to be capable of byte-range requests
  275.                             uint16 *stype)    // stream modes other than the default (NPNormal)
  276. {
  277.     if (instance == NULL)
  278.         return NPERR_INVALID_INSTANCE_ERROR;
  279.     PluginInstance* This = (PluginInstance*) instance->pdata;
  280.  
  281.     This->fBusy = TRUE;            // We’re loading now
  282.  
  283.     return NPERR_NO_ERROR;
  284. }
  285.  
  286.  
  287.  
  288.  
  289. //
  290. // *Developers*: 
  291. // These next 2 functions are directly relevant in a plug-in which handles the
  292. // data in a streaming manner.  If you want zero bytes because no buffer space
  293. // is YET available, return 0.  As long as the stream has not been written
  294. // to the plugin, Navigator will continue trying to send bytes.  If the plugin
  295. // doesn't want them, just return some large number from NPP_WriteReady(), and
  296. // ignore them in NPP_Write().  For a NP_ASFILE stream, they are still called
  297. // but can safely be ignored using this strategy.
  298. //
  299.  
  300. int32 STREAMBUFSIZE = 0X0FFFFFFF;   // If we are reading from a file in NPAsFile
  301.                                     // mode so we can take any size stream in our
  302.                                     // write call (since we ignore it)
  303.  
  304. //------------------------------------------------------------------------------------
  305. // NPP_WriteReady:
  306. //------------------------------------------------------------------------------------
  307. int32 
  308. NPP_WriteReady(NPP instance, NPStream *stream)
  309. {
  310.     if (instance != NULL)
  311.     {
  312.         PluginInstance* This = (PluginInstance*) instance->pdata;
  313.     
  314.     }
  315.  
  316.     return STREAMBUFSIZE;   // Number of bytes ready to accept in NPP_Write()
  317. }
  318.  
  319.  
  320.  
  321. //------------------------------------------------------------------------------------
  322. // NPP_Write:
  323. //------------------------------------------------------------------------------------
  324. int32 
  325. NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer)
  326. {
  327.     if (instance != NULL)
  328.     {
  329.         PluginInstance* This = (PluginInstance*) instance->pdata;
  330.     
  331.         AppendData(This, (unsigned long*) &len, buffer);
  332.     }
  333.  
  334.     return len;             // The number of bytes accepted
  335. }
  336.  
  337.  
  338.  
  339. //------------------------------------------------------------------------------------
  340. // NPP_DestroyStream:
  341. // Called to close and delete the stream.
  342. //------------------------------------------------------------------------------------
  343. NPError 
  344. NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason)
  345. {
  346.     if (instance == NULL)
  347.         return NPERR_INVALID_INSTANCE_ERROR;
  348.     PluginInstance* This = (PluginInstance*) instance->pdata;
  349.  
  350.     This->fBusy = false;    // No longer loading
  351.  
  352.     if (This->fBuffer != NULL)    // Pictures have 512 extra bytes of data at the beginning
  353.     {
  354.  
  355.         if (This->fModel != NULL)
  356.         {
  357.             ::Q3Object_Dispose(This->fModel);
  358.             This->fModel = NULL;
  359.         }
  360.         
  361.         ::HLock(This->fBuffer);
  362.  
  363.         This->fModel = MyNewModelFromBuffer( This ) ;
  364.  
  365.         ::HUnlock(This->fBuffer);
  366.         
  367.         ::DisposeHandle(This->fBuffer);
  368.         This->fBuffer = NULL;
  369.         This->fBufferLength = 0;
  370.  
  371.         AdjustCamera(This, This->fRect.right, This->fRect.bottom ) ;
  372.     
  373.         if (StartDraw(This->fWindow))
  374.         {
  375.             DoDraw(This);
  376.             EndDraw(This->fWindow);
  377.         }
  378.     }
  379.  
  380.     return NPERR_NO_ERROR;
  381. }
  382.  
  383.  
  384. //------------------------------------------------------------------------------------
  385. // NPP_StreamAsFile:
  386. //------------------------------------------------------------------------------------
  387. void NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
  388. {
  389. // We don’t support files
  390. }
  391.  
  392.  
  393.  
  394. //------------------------------------------------------------------------------------
  395. // NPP_Print:
  396. //------------------------------------------------------------------------------------
  397. void NPP_Print(NPP instance, NPPrint* printInfo)
  398. {
  399.     if (instance != NULL)
  400.     {
  401.         PluginInstance* This = (PluginInstance*) instance->pdata;
  402.     
  403.         if (printInfo->mode == NP_FULL)
  404.         {
  405.             //
  406.             // If we’re fullscreen, we don’t want to take over printing,
  407.             // so return false.  NPP_Print will be called again with
  408.             // mode == NP_EMBED.
  409.             //
  410.             printInfo->print.fullPrint.pluginPrinted = false;
  411.         }
  412.         else    // If not fullscreen, we must be embedded
  413.         {
  414.             NPWindow* printWindow = &(printInfo->print.embedPrint.window);
  415.             if (StartDraw(printWindow))
  416.             {
  417.                 DoDraw(This);
  418.                 EndDraw(printWindow);
  419.             }
  420.         }
  421.     }
  422.  
  423. }
  424.  
  425.  
  426. //------------------------------------------------------------------------------------
  427. // NPP_HandleEvent:
  428. // Mac-only.
  429. //------------------------------------------------------------------------------------
  430. int16 NPP_HandleEvent(NPP instance, void* event)
  431. {
  432.     Boolean eventHandled = false;
  433.     if (instance == NULL)
  434.         return eventHandled;
  435.         
  436.     PluginInstance* This = (PluginInstance*) instance->pdata;
  437.     if (This != NULL && event != NULL)
  438.     {
  439.         EventRecord* ev = (EventRecord*) event;
  440.         switch (ev->what)
  441.         {
  442.             //
  443.             // Draw ourselves on update events
  444.             //
  445.             case updateEvt:
  446.                 DoDraw(This);
  447.                 eventHandled = true;
  448.                 break;
  449.             
  450.             case nullEvent:
  451.                 // we received a null event, rotate the model
  452.                 TQ3Matrix4x4    tmp;
  453.                 
  454.             
  455.                 if (StartDraw(This->fWindow))
  456.                 {
  457.                     DoDraw(This);
  458.                     EndDraw(This->fWindow);
  459.                 }
  460.                     Q3Matrix4x4_SetRotate_XYZ(&tmp, 0.1, 0.12, 0.08);
  461.                     Q3Matrix4x4_Multiply(&This->fRotation, &tmp, &This->fRotation);
  462.                 break;
  463.             
  464.             default:
  465.                 break;
  466.         }
  467.     }
  468.     
  469.     return eventHandled;
  470. }
  471.  
  472.  
  473.  
  474. //------------------------------------------------------------------------------------
  475. // AppendData:
  476. //------------------------------------------------------------------------------------
  477. OSErr AppendData(PluginInstance* This, unsigned long* len, void *buffer)
  478. {
  479.     OSErr resultCode = noErr;
  480.  
  481.     if (This->fBuffer == NULL)  // Have not yet allocated buffer
  482.     {
  483.         Size appMem = 0;
  484.         Size tmpMem = 0;
  485.  
  486.         This->fBufferLength = 0;
  487.  
  488.         appMem = ::MaxMem(&appMem);
  489.         tmpMem = ::TempMaxMem(&tmpMem);
  490.  
  491.  
  492.         // Allocate memory in the heap with the most room.
  493.         if (tmpMem >= appMem)
  494.         {
  495.             This->fBuffer = ::TempNewHandle( *len, &resultCode) ;
  496.         }
  497.         else 
  498.         {
  499.             This->fBuffer = ::NewHandle(*len) ;
  500.         }
  501.  
  502.         if ((This->fBuffer == NULL) || (resultCode != noErr))
  503.         {
  504.             if (resultCode != noErr) 
  505.             {
  506.                 resultCode = MemError();
  507.             }
  508.  
  509.             /// DebugStr("\p Out of Memory") ; 
  510.             
  511.             *len = 0;
  512.             return resultCode;
  513.         }
  514.     }
  515.     else
  516.     {
  517.         ::SetHandleSize(This->fBuffer, GetHandleSize(This->fBuffer)+*len);
  518.     }
  519.  
  520.     ::BlockMove(buffer, (*This->fBuffer)+This->fBufferLength, *len);
  521.     
  522.     This->fBufferLength += *len;
  523.  
  524.     return noErr;
  525. }
  526.  
  527.  
  528. //------------------------------------------------------------------------------------
  529. // StartDraw:
  530. //------------------------------------------------------------------------------------
  531. Boolean StartDraw(NPWindow* window)
  532. {
  533.     if (window == NULL)
  534.         return FALSE;
  535.     NP_Port* port = (NP_Port*) window->window;
  536.     if (window->clipRect.left < window->clipRect.right)
  537.     {
  538.     // Preserve the old port
  539.         ::GetPort((GrafPtr*)&gOldPort);
  540.         ::SetPort((GrafPtr)port->port);
  541.     // Preserve the old drawing environment
  542.         gSavePort.portRect = port->port->portRect;
  543.         gSavePort.txFont = port->port->txFont;
  544.         gSavePort.txFace = port->port->txFace;
  545.         gSavePort.txMode = port->port->txMode;
  546.         gSavePort.rgbFgColor = port->port->rgbFgColor;
  547.         gSavePort.rgbBkColor = port->port->rgbBkColor;
  548.         ::GetClip(gSavePort.clipRgn);
  549.     // Setup our drawing environment
  550.         Rect clipRect;
  551.         clipRect.top = window->clipRect.top + port->porty;
  552.         clipRect.left = window->clipRect.left + port->portx;
  553.         clipRect.bottom = window->clipRect.bottom + port->porty;
  554.         clipRect.right = window->clipRect.right + port->portx;
  555.         ::SetOrigin(port->portx,port->porty);
  556.         ::ClipRect(&clipRect);
  557.         clipRect.top = clipRect.left = 0;
  558.         TextSize(window->height);
  559.         TextFont(geneva);
  560.         TextMode(srcCopy);
  561.         RGBColor  col;
  562.         col.red = col.green = col.blue = 30000;
  563.         RGBForeColor(&col);
  564.         col.red = col.green = col.blue = 65000;
  565.         RGBBackColor(&col);
  566.         return TRUE;
  567.     }
  568.     else
  569.         return FALSE;
  570. }
  571.  
  572.  
  573. //------------------------------------------------------------------------------------
  574. // EndDraw:
  575. //------------------------------------------------------------------------------------
  576. void EndDraw(NPWindow* window)
  577. {
  578.     NP_Port* port = (NP_Port*) window->window;
  579.     ::SetOrigin(gSavePort.portRect.left, gSavePort.portRect.top);
  580.     ::SetClip(gSavePort.clipRgn);
  581.     CGrafPtr myPort;
  582.     ::GetPort((GrafPtr*)&myPort);
  583.     myPort->txFont = gSavePort.txFont;
  584.     myPort->txFace = gSavePort.txFace;
  585.     myPort->txMode = gSavePort.txMode;
  586.     ::RGBForeColor(&gSavePort.rgbFgColor);
  587.     ::RGBBackColor(&gSavePort.rgbBkColor);
  588.     ::SetPort((GrafPtr)gOldPort);
  589. }
  590.  
  591.  
  592. //------------------------------------------------------------------------------------
  593. // DoDraw:
  594. //------------------------------------------------------------------------------------
  595. void DoDraw(PluginInstance* This)
  596. {
  597.     if (This->fBusy )    // Do not draw if we are not done
  598.         return;
  599.  
  600.     DocumentDraw3DData( This ) ;
  601. }
  602.  
  603.